-
-
Notifications
You must be signed in to change notification settings - Fork 129
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix and extend wcs1d-fits
loader for multi-D WCS
#1009
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #1009 +/- ##
==========================================
+ Coverage 70.01% 70.26% +0.24%
==========================================
Files 64 64
Lines 4346 4419 +73
==========================================
+ Hits 3043 3105 +62
- Misses 1303 1314 +11 ☔ View full report in Codecov by Sentry. |
So this fixes #592 ? |
This should work for your example. |
I was somewhat surprised when updating the writer, that there are apparently WCS that have a |
@@ -707,11 +707,10 @@ def test_tabular_fits_compressed(compress, tmpdir): | |||
|
|||
|
|||
@pytest.mark.parametrize("spectral_axis", | |||
['wavelength', 'frequency', 'energy', 'wavenumber']) | |||
['WAVE', 'FREQ', 'ENER', 'WAVN']) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just some minor context: if I recall, the spectral axis names were meant to correspond with the class properties and not the FITS naming standard. Either way, it's not an issue, but figured the history of the usage might add some context.
I have added read and write for |
Apparently something in oldestdeps is pulling numpy 1.24.2 in, overriding |
Hmm easy way out is to bump min version of numpy though even that might not work. Another thing you can do is to hunt down what is overwriting the numpy pin and pin that package to an older version as well.
Definitely needed if you want it to be generic enough since Spectrum1D does have an uncertainty component. I just didn't do it downstream because apparently model fitting in Cubeviz does not generate that. |
de33ac4
to
20f9de7
Compare
wcs1d-fits
loader for multi-D WCSwcs1d-fits
loader for multi-D WCS
Marking this as ready for review now, as the multi-HDU format for masks and uncertainties is functional (unless there are more labels the loader needs to identify). specutils/specutils/io/default_loaders/sixdfgs_reader.py Lines 188 to 189 in 6eb7f96
could still be added |
wcs1d-fits
loader for multi-D WCSwcs1d-fits
loader for multi-D WCS
verbose : bool | ||
hdu : int, str or None, optional | ||
The index or name of the HDU to load into this spectrum | ||
(default: find 1st applicable `ImageHDU`). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This confuses me. Is this loader only for image? A spectrum can also come as table HDU, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
wcs1d handles only spectra with flux represented as image and spectral axis defined by the WCS; tables are covered by tabular-fits
. That already supports masks and uncertainties, more or less, which are simply additional table columns in that representation.
uncertainty_name : str or `None`, optional | ||
HDU name to store uncertainty under (default set from type; `None`: do not save) | ||
unit : str or :class:`~astropy.units.Unit`, optional | ||
Unit for the flux (and associated uncertainty; defaults to `spectrum.flux.unit`) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unless spectrum.flux.unit
actually generates API doc, use double-backticks. I cannot check because RTD build failed on your PR. Also see #1028.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
spectrum.flux
does, but not specifically unit
, is that what you mean? I don't know if the loaders themselves generate API docs, or rather where they might be linked from ;-)
Thanks for pointing out the RTD failure; throws in all current PRs and does not seem related – from a quick glance some parsing error related to reproject
, but needs further investigation – oh, it already does!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually it seems none of the functions in default_loaders
have any docs built at all, though it would certainly be useful to have them and link them in https://specutils.readthedocs.io/en/latest/spectrum1d.html#list-of-loaders.
Sorry, I think my fixes to the tests caused a conflict here, so you need to rebase and resolve the conflict. |
d5705fa
to
696a0b3
Compare
Doh, that seems to have screwed up more commits than I even had in this branch! |
@@ -875,7 +1026,7 @@ def test_wcs1d_fits_compressed(compress, tmp_path): | |||
# Try again without compression suffix: | |||
with warnings.catch_warnings(): | |||
warnings.simplefilter('ignore', FITSFixedWarning) | |||
os.system(f'mv {tmpfile}{ext[compress]} {tmpfile}') | |||
os.system(f'mv {tmpfile}.{ext[compress]} {tmpfile}') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Side note: Why call os.system
instead of shutil
? Anyways, I guess fixing this is out of scope.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps because I (or whoever wrote the tests originally) did not know any better at the time, or perhaps because os.system
is needed anyway to do the compression – or is there also some kind of exec
functionality with shutil
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see how "mv" cares about compression? https://docs.python.org/3/library/shutil.html#shutil.move
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not at all, I guess 😄; just meant that it's kind of the direct counterpart to
os.system(f'{compress} {tmpfile}')
just above, and that cannot be replaced with shutil.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Anyway there are a couple of those compress-rename duos, so refactoring them would be better left to a separate PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I left what general review comments I could. Now it is up to specutils maintainers to review. Thanks!
@@ -157,12 +246,16 @@ def wcs1d_fits_writer(spectrum, file_name, hdu=0, update_header=False, **kwargs) | |||
raise ValueError(f'Only Spectrum1D objects with valid WCS can be written as wcs1d: {err}') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not that familiar with the workings of WCS (and especially wcs.to_fits()
) - is there any realistic scenario for setting hdu
to a value other than 0, given that the initial hdulist
is always created from the spectrum's WCS anyway? I guess what I'm asking is, is there really utility in having empty HDUs in front of the specified hdu
index? There are no options to specify the HDU numbers for uncertainty and mask, so it's not like the user could write out in order [uncertainty, mask, flux], for example. Maybe we just get rid of the hdu
argument altogether?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As long as this is not considered "public" API and ok to break just like that, I agree.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not that familiar with the workings of WCS (and especially
wcs.to_fits()
) - is there any realistic scenario for settinghdu
to a value other than 0, given that the initialhdulist
is always created from the spectrum's WCS anyway?
It's not as much associated to using a WCS, but rather to the flux being stored in an ImageHDU, which can be the PrimaryHDU or an extension, while tables can only be stored in extensions. However for symmetry reasons or whatever sometimes writing the image to an extension, too, and using just a basic PrimaryHDU, is desired (there was one comment somewhere sketching just this scenario, but I cannot find it either in the Slack discussion or any related issue now).
For the record: that example is right in #592 (comment) that set this whole thing off.
I think originally accepting any value for hdu
was just introduced as a poor substitute for not being able to write multiple spectra to one file/hdulist, but there is probably no real use case for this. For hdu=1
I'd say there is, and this should still remain available.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the explanation...I guess it makes sense to leave it in then for now.
Thanks @dhomeier, this is a great improvement. I had one question and left one suggestion, and there's one suggestion from @pllim remaining, but other than that I think this looks good. I appreciate the test coverage. I was going to say, maybe we change the name from |
I had been thinking about that some times; to me the distinctive property was actually usually having the flux as Image data rather than a table column, so having something like |
@dhomeier Can I commit the last suggestions for you and merge this? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Approved, need to commit last two suggestions before merging.
Co-authored-by: P. L. Lim <2090236+pllim@users.noreply.github.com>
Hmm does this mean we should ditch Jdaviz custom writer and use this? |
I've included them in some more local updates I had made; should be good to merge then. |
Blast, I went ahead and committed and merged, thinking you might be done and logged off for the day. Are your other updates worth opening a follow-up PR for? Sorry about that. |
Ah, remote tests are taking too long here (spPlate really bogs everything down). |
Thanks, @dhomeier ! I am trying out this improved format over at spacetelescope/jdaviz#2094 but I encountered error. Perhaps we need an extra step to convert bool mask to uint16 (I guess it could be uint8 but uint16 is common in bit-plane format)?
https://github.com/spacetelescope/jdaviz/actions/runs/4451633462/jobs/7818514722?pr=2094 |
To address #592 (comment); quick fix for enabling writing of spectral cubes with celestial components in WCS.
Reading in with the full WCS is now supported as well, plus adding
mask
anduncertainty
to the attributes read from file.The latter at this point are still limited to the format storing them all in different ImageHDUs; an alternative common format storing the fields as sub-arrays of an N+1 image yet to be implemented.
Fixes #592